﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Text;
using DomenModel;
using System.Web.Security;
using System.Configuration;
using Infrastructure.Repositories;
using Model.Repositories;
using Model.Service;
using Model.Repositories.Interfaces;

namespace Infrastructure.Service
{
    public class MerchandiseService : IMerchandiseService
    {
        private IOrderDetailsCrud _dbOrderDetails;
        private IOrderCrud _dbOrder;

        public MerchandiseService(IOrderDetailsCrud _dbOrderDetails, IOrderCrud _dbOrder)
        {
            this._dbOrderDetails = _dbOrderDetails;
            this._dbOrder = _dbOrder;
        }

        public MerchandiseService()
        {
            _dbOrderDetails = new OrderDetailsRepo();
            _dbOrder = new OrderRepo();
        }


        public List<Order> GetPaginationListOfOrders(int page, int itemsOnPage, string orderOrdersBy)
        {
            Expression<Func<Order, string>> predicate;

            orderOrdersBy = orderOrdersBy ?? "OrderId";
            bool descending = false;

            string[] st = orderOrdersBy.Split(' ');
            if (st.Length == 2) descending = true;

            switch (st[0])
            {
                //case "OrderId":
                  //  predicate = p => p.OrderId.ToString();
                  //  break;
               // case "UserId":
                   // predicate = p => p.UserId.ToString();
                  //  break;
              
                case "Assignee":
                    predicate = p => p.Assigned;
                    break;

                case "Accepted":
                    predicate = p => p.Accepted.ToString();
                    break;

                case "Delivered":
                    predicate = p => p.Delivered.ToString();
                    break;

                default:
                    //predicate = p => p.OrderId.ToString();
                    predicate = p => p.Assigned;
                    break;
            }
            var list = _dbOrder.GetListForPagination(page, itemsOnPage, predicate, descending);
            return list;
        }

        public List<Order> GetPaginationWithFilter(int page, int itemsOnPage, string orderOrdersBy, string searchString,
                                                   string listSelectField, string listSelectCondition)
        {
            Expression<Func<Order, string>> predicate;

            orderOrdersBy = orderOrdersBy ?? "OrderId";
            bool descending = false;

            string[] st = orderOrdersBy.Split(' ');
            if (st.Length == 2) descending = true;

            switch (st[0])
            {
                case "OrderId":
                    predicate = p => p.OrderId.ToString();
                    break;
                case "UserId":
                    predicate = p => p.UserId.ToString();
                    break;

                case "Assignee":
                    predicate = p => p.Assigned;
                    break;

                case "Accepted":
                    predicate = p => p.Accepted.ToString();
                    break;

                case "Delivered":
                    predicate = p => p.Delivered.ToString();
                    break;

                default:
                    predicate = p => p.OrderId.ToString();
                    break;
            }
            
            var filterExpression = Filter(searchString, listSelectField, listSelectCondition);
            var list = _dbOrder.GetListForPaginationWithFilter(page, itemsOnPage, filterExpression, predicate, descending);
            return list;
        }


        private Expression<Func<Order, bool>> Filter(string searchString, string listSelectField, string listSelectCondition)
        {
            var param = Expression.Parameter(typeof(Order), "u");
            MemberExpression prop;
            switch (listSelectField)
            {
                case "OrderId":
                    prop = Expression.Property(param, typeof(Order).GetProperty("OrderId"));
                    break;
                case "UserId":
                    prop = Expression.Property(param, typeof(Order).GetProperty("UserId"));
                    break;
                case "Assignee":
                    prop = Expression.Property(param, typeof(Order).GetProperty("Assigned"));
                    break;
                case "Accepted":
                    prop = Expression.Property(param, typeof(Order).GetProperty("Accepted"));
                    break;
                case "Delivered":
                    prop = Expression.Property(param, typeof(Order).GetProperty("Delivered"));
                    break;

                //case "First Name":
                  //  prop = Expression.Property(param, typeof(User).GetProperty("FirstName"));
                   // break;

               // case "Last Name":
                  //  prop = Expression.Property(param, typeof(User).GetProperty("LastName"));
                  //  break;

                default:
                    prop = Expression.Property(param, typeof(Order).GetProperty("OrderId"));
                    break;
            }

            string selectedCondition;
            switch (listSelectCondition)
            {
                case "starts with":
                    selectedCondition = "StartsWith";
                    break;

                case "equals":
                    selectedCondition = "Equals";
                    break;

                default:
                    selectedCondition = "Contains";
                    break;
            }

            MethodCallExpression startsWith = Expression.Call(
                prop,
                typeof(String).GetMethod(selectedCondition, new Type[] { typeof(String) }),
                Expression.Constant(searchString)
                );

            return Expression.Lambda<Func<Order, bool>>(startsWith, param);

        }


        public Order GetOrder(int id)
        {
            return _dbOrder.GetById(id);
            
        }

        public bool EditOrder(Order order)
        {
            _dbOrder.Update(order);
            return true;
        }

        public long GetCountOfOrders()
        {
            return _dbOrder.GetCountOfOrders();
        }

        public long GetCountOfOrders(string searchString, string listSelectField, string listSelectCondition)
        {
            var filterExpression = Filter(searchString, listSelectField, listSelectCondition);
            var count = _dbOrder.GetCountOfOrders(filterExpression);
            return count;
        }

        public List<OrderDetails> GetOrdersDetailsOfOrder(int orderId)
        {
            var list = _dbOrderDetails.GetCollection(orderId);
            return list;
        }


    }
}
